/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

using System;
using System.Collections.Generic;

namespace FaceCat {
    /// <summary>
    /// 图层
    /// </summary>
    public class FCDiv : FCView, FCEventCallBack, FCKeyEventCallBack, FCTouchEventCallBack {
        /// <summary>
        /// 创建支持滚动条的视图
        /// </summary>
        public FCDiv() {
            m_size = new FCSize(100, 100);
        }

        /// <summary>
        /// 是否正在滚动2
        /// </summary>
        public bool m_isDragScrolling2;

        /// <summary>
        /// 必须更新
        /// </summary>
        protected bool m_mustUpdate;

        /// <summary>
        /// 是否准备拖动滚动
        /// </summary>
        public bool m_readyToDragScroll;

        /// <summary>
        /// 开始移动的位置
        /// </summary>
        private FCPoint m_startMovePoint;

        /// <summary>
        /// 开始移动的横向位置
        /// </summary>
        private int m_startMovePosX;

        /// <summary>
        /// 开始移动的纵向位置
        /// </summary>
        private int m_startMovePosY;

        /// <summary>
        /// 开始移动时间
        /// </summary>
        private DateTime m_startMoveTime;

        public bool m_allowDragScroll = false;

        /// <summary>
        /// 获取是否允许拖动滚动
        /// </summary>
        public virtual bool allowDragScroll() {
            return m_allowDragScroll;
        }

        /// <summary>
        /// 设置是否允许拖动滚动
        /// </summary>
        public virtual void setAllowDragScroll(bool value) {
            m_allowDragScroll = value;
        }

        public FCHScrollBar m_hScrollBar;

        /// <summary>
        /// 获取横向滚动条
        /// </summary>
        public virtual FCHScrollBar getHScrollBar() {
            if (getNative() != null && m_showHScrollBar) {
                if (m_hScrollBar == null) {
                    FCHost host = getNative().getHost();
                    m_hScrollBar = host.createInternalView(this, "hscrollbar") as FCHScrollBar;
                    addView(m_hScrollBar);
                    //注册按钮的事件
                    m_hScrollBar.getAddButton().addEvent(this, "onkeydown", null);
                    m_hScrollBar.getAddButton().addEvent(this, "ontouchwheel", null);
                    m_hScrollBar.getBackButton().addEvent(this, "onkeydown", null);
                    m_hScrollBar.getBackButton().addEvent(this, "ontouchwheel", null);
                    m_hScrollBar.getReduceButton().addEvent(this, "onkeydown", null);
                    m_hScrollBar.getReduceButton().addEvent(this, "ontouchwheel", null);
                    m_hScrollBar.getScrollButton().addEvent(this, "onkeydown", null);
                    m_hScrollBar.getScrollButton().addEvent(this, "ontouchwheel", null);
                }
                return m_hScrollBar;
            }
            return null;
        }

        public bool m_showHScrollBar = false;

        /// <summary>
        /// 获取是否显示横向滚动条
        /// </summary>
        public virtual bool showHScrollBar() {
            return m_showHScrollBar;
        }

        /// <summary>
        /// 设置是否显示横向滚动条
        /// </summary>
        public virtual void setShowHScrollBar(bool value) {
            m_showHScrollBar = value;
        }

        public bool m_isDragScrolling;

        /// <summary>
        /// 获取是否正在被拖动
        /// </summary>
        public virtual bool isDragScrolling() {
            return m_isDragScrolling;
        }

        public bool m_showVScrollBar = false;

        /// <summary>
        /// 获取是否显示纵向滚动条
        /// </summary>
        public virtual bool showVScrollBar() {
            return m_showVScrollBar;
        }

        /// <summary>
        /// 设置是否显示纵向滚动条
        /// </summary>
        public void setShowVScrollBar(bool value) {
            m_showVScrollBar = value;
        }

        public FCVScrollBar m_vScrollBar;

        /// <summary>
        /// 获取纵向滚动条
        /// </summary>
        public virtual FCVScrollBar getVScrollBar() {
            if (getNative() != null && m_showVScrollBar) {
                if (m_vScrollBar == null) {
                    FCHost host = getNative().getHost();
                    m_vScrollBar = host.createInternalView(this, "vscrollbar") as FCVScrollBar;
                    addView(m_vScrollBar);
                    //注册按钮的事件
                    m_vScrollBar.getAddButton().addEvent(this, "onkeydown", null);
                    m_vScrollBar.getAddButton().addEvent(this, "ontouchwheel", null);
                    m_vScrollBar.getBackButton().addEvent(this, "onkeydown", null);
                    m_vScrollBar.getBackButton().addEvent(this, "ontouchwheel", null);
                    m_vScrollBar.getReduceButton().addEvent(this, "onkeydown", null);
                    m_vScrollBar.getReduceButton().addEvent(this, "ontouchwheel", null);
                    m_vScrollBar.getScrollButton().addEvent(this, "onkeydown", null);
                    m_vScrollBar.getScrollButton().addEvent(this, "ontouchwheel", null);
                }
                return m_vScrollBar;
            }
            return null;
        }

        /// <summary>
        /// 触发事件
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="sender"></param>
        /// <param name="key"></param>
        /// <param name="invoke"></param>
        public virtual void callEvent(String eventName, Object sender, Object invoke) {
        }

        /// <summary>
        /// 滚动按钮键盘按下事件
        /// </summary>
        /// <param name="sender">发送者</param>
        /// <param name="key">按键</param>
        public virtual void callKeyEvent(String eventName, Object sender, char key, Object invoke) {
            if (m_hScrollBar != null) {
                for (int i = 0; i < m_hScrollBar.m_views.size(); i++) {
                    if (m_hScrollBar.m_views.get(i) == sender) {
                        onKeyDown(key);
                        return;
                    }
                }
            }
            if (m_vScrollBar != null) {
                for (int i = 0; i < m_vScrollBar.m_views.size(); i++) {
                    if (m_vScrollBar.m_views.get(i) == sender) {
                        onKeyDown(key);
                        return;
                    }
                }
            }
            
        }

        /// <summary>
        /// 滚动按钮触摸滚动事件
        /// </summary>
        /// <param name="sender">发送者</param>
        /// <param name="touchInfo">触摸信息</param>
        public virtual void callTouchEvent(String eventName, Object sender, FCTouchInfo touchInfo, Object invoke) {
            FCTouchInfo newTouchInfo = touchInfo.clone();
            newTouchInfo.m_firstPoint = getTouchPoint();
            newTouchInfo.m_secondPoint = getTouchPoint();
            onTouchWheel(newTouchInfo);
        }

        /// <summary>
        /// 清除所有的控件
        /// </summary>
        public virtual void clearChildViews()
        {
            ArrayList<FCView> views = new ArrayList<FCView>();
            foreach (FCView view in m_views)
            {
                if (view != m_hScrollBar && view != m_vScrollBar)
                {
                    views.add(view);
                }
            }
            foreach (FCView view in views)
            {
                removeView(view);
                view.delete();
            }
            views.clear();
        }

        /// <summary>
        /// 获取内容的高度
        /// </summary>
        /// <returns>高度</returns>
        public virtual int getContentHeight() {
            if (!m_showVScrollBar)
            {
                return getHeight();
            }
            FCVScrollBar vScrollBar = getVScrollBar();
            FCHScrollBar hScrollBar = getHScrollBar();
            int hmax = 0;
            ArrayList<FCView> views = m_views;
            int viewSize = views.size();
            for (int i = 0; i < viewSize; i++) {
                FCView view = views[i];
                if (view.isVisible() && view != hScrollBar && view != vScrollBar) {
                    int bottom = view.getBottom();
                    if (bottom > hmax) {
                        hmax = bottom;
                    }
                }
            }
            return hmax;
        }

        /// <summary>
        /// 获取内容的宽度
        /// </summary>
        /// <returns>宽度</returns>
        public virtual int getContentWidth() {
            if (!m_showHScrollBar)
            {
                return getWidth();
            }
            FCHScrollBar hScrollBar = getHScrollBar();
            FCVScrollBar vScrollBar = getVScrollBar();
            int wmax = 0;
            ArrayList<FCView> views = m_views;
            int viewSize = views.size();
            for (int i = 0; i < viewSize; i++) {
                FCView view = views[i];
                if (view.isVisible() && view != hScrollBar && view != vScrollBar) {
                    int right = view.getRight();
                    if (right > wmax) {
                        wmax = right;
                    }
                }
            }
            return wmax;
        }

        /// <summary>
        /// 获取视图类型
        /// </summary>
        /// <returns>视图类型</returns>
        public override String getViewType() {
            return "Div";
        }

        /// <summary>
        /// 获取显示偏移坐标
        /// </summary>
        /// <returns>坐标</returns>
        public override FCPoint getDisplayOffset() {
            return new FCPoint((m_hScrollBar != null && m_hScrollBar.isVisible()) ? m_hScrollBar.getPos() : 0,
                    (m_vScrollBar != null && m_vScrollBar.isVisible()) ? m_vScrollBar.getPos() : 0);
        }

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">返回属性值</param>
        /// <param name="type">返回属性类型</param>
        public override void getAttribute(String name, ref String value, ref String type) {
            switch (name)
            {
                case "allowdragscroll":
                    type = "bool";
                    value = FCTran.boolToStr(allowDragScroll());
                    break;
                case "showhscrollbar":
                    type = "bool";
                    value = FCTran.boolToStr(showHScrollBar());
                    break;
                case "showvscrollbar":
                    type = "bool";
                    value = FCTran.boolToStr(showVScrollBar());
                    break;
                default:
                    base.getAttribute(name, ref value, ref type);
                    break;
            }
        }

        /// <summary>
        /// 获取属性名称列表
        /// </summary>
        /// <returns>属性名称列表</returns>
        public override ArrayList<String> getAttributeNames() {
            ArrayList<String> attributeNames = base.getAttributeNames();
            attributeNames.AddRange(new String[] { "AllowDragScroll", "ShowHScrollBar", "ShowVScrollBar" });
            return attributeNames;
        }

        /// <summary>
        /// 向下滚动一行
        /// </summary>
        public virtual void lineDown() {
            if (m_vScrollBar != null && m_vScrollBar.isVisible()) {
                m_vScrollBar.lineAdd();
            }
        }

        /// <summary>
        /// 向左滚动一行
        /// </summary>
        public virtual void lineLeft() {
            if (m_hScrollBar != null && m_hScrollBar.isVisible()) {
                m_hScrollBar.lineReduce();
            }
        }

        /// <summary>
        /// 向右滚动一行
        /// </summary>
        public virtual void lineRight() {
            if (m_hScrollBar != null && m_hScrollBar.isVisible()) {
                m_hScrollBar.lineAdd();
            }
        }

        /// <summary>
        /// 向上滚动一行
        /// </summary>
        public virtual void lineUp() {
            if (m_vScrollBar != null && m_vScrollBar.isVisible()) {
                m_vScrollBar.lineReduce();
            }
        }

        /// <summary>
        /// 拖动准备方法
        /// </summary>
        /// <param name="startOffset">可以拖动的偏移坐标量</param>
        public override void onDragReady(ref FCPoint startOffset) {
            startOffset.x = 0;
            startOffset.y = 0;
        }

        /// <summary>
        /// 拖动滚动结束
        /// </summary>
        public virtual void onDragScrollEnd() {
            m_isDragScrolling = false;
            if (m_readyToDragScroll) {
                DateTime nowTime = DateTime.Now;
                FCPoint newPoint = getNative().getTouchPoint();
                if (m_hScrollBar != null && m_hScrollBar.isVisible()) {
                    if (Math.Abs(newPoint.x - m_startMovePoint.x) > 50 || m_hScrollBar.getAddSpeed() != 0)
                    {
                        m_hScrollBar.onAddSpeedScrollStart(m_startMoveTime.Ticks, nowTime.Ticks, m_startMovePoint.x, newPoint.x);
                    }
                }
                if (m_vScrollBar != null && m_vScrollBar.isVisible()) {
                    if (Math.Abs(newPoint.y - m_startMovePoint.y) > 50 || m_vScrollBar.getAddSpeed() != 0)
                    {
                        m_vScrollBar.onAddSpeedScrollStart(m_startMoveTime.Ticks, nowTime.Ticks, m_startMovePoint.y, newPoint.y);
                    }
                }
                m_readyToDragScroll = false;
                invalidate();
            }
        }

        /// <summary>
        /// 拖动滚动中
        /// </summary>
        public virtual void onDragScrolling() {
            int width = getWidth(), height = getHeight();
            if (m_allowDragScroll && m_readyToDragScroll) {
                if (!onDragScrollPermit()) {
                    m_readyToDragScroll = false;
                    return;
                }
                bool paint = false;
                FCPoint newPoint = getNative().getTouchPoint();
                if (m_hScrollBar != null && m_hScrollBar.isVisible()) {
                    if (Math.Abs(newPoint.x - m_startMovePoint.x) > width / 10) {
                        m_isDragScrolling2 = true;
                        m_native.m_touchDownView = this;
                        m_native.m_touchMoveView = this;
                        m_native.m_focusedView = this;
                    }
                    int newPos = m_startMovePosX + m_startMovePoint.x - newPoint.x;
                    if (newPos != m_hScrollBar.getPos()) {
                        m_hScrollBar.setPos(newPos);
                        m_hScrollBar.update();
                        paint = true;
                    }
                }
                if (m_vScrollBar != null && m_vScrollBar.isVisible()) {
                    if (Math.Abs(newPoint.y - m_startMovePoint.y) > height / 10) {
                        m_isDragScrolling2 = true;
                        m_native.m_touchDownView = this;
                        m_native.m_touchMoveView = this;
                        m_native.m_focusedView = this;
                    }
                    int newPos = m_startMovePosY + m_startMovePoint.y - newPoint.y;
                    if (newPos != m_vScrollBar.getPos()) {
                        m_vScrollBar.setPos(newPos);
                        m_vScrollBar.update();
                        paint = true;
                    }
                }
                if (paint) {
                    m_isDragScrolling = true;
                    invalidate();
                }
            }
        }

        /// <summary>
        /// 拖动滚动许可检查
        /// </summary>
        public virtual bool onDragScrollPermit() {
            FCView focusedView = getNative().getFocusedView();
            if (focusedView != null) {
                if (focusedView.isDragging()) {
                    return false;
                }
                if (focusedView is FCGridColumn) {
                    return false;
                }
                if (focusedView.getParent() != null) {
                    if (focusedView.getParent() is FCScrollBar) {
                        return false;
                    }
                }
            }
            return true;
        }

        /// <summary>
        /// 拖动滚动开始
        /// </summary>
        public virtual void onDragScrollStart() {
            m_isDragScrolling = false;
            m_isDragScrolling2 = false;
            FCView focusedView = getNative().getFocusedView();
            if (m_hScrollBar != null && m_hScrollBar.isVisible()) {
                if (focusedView == m_hScrollBar.getAddButton()
                    || focusedView == m_hScrollBar.getReduceButton()
                    || focusedView == m_hScrollBar.getBackButton()
                    || focusedView == m_hScrollBar.getScrollButton()) {
                    m_hScrollBar.setAddSpeed(0);
                    return;
                }
            }
            if (m_vScrollBar != null && m_vScrollBar.isVisible()) {
                if (focusedView == m_vScrollBar.getAddButton()
             || focusedView == m_vScrollBar.getReduceButton()
             || focusedView == m_vScrollBar.getBackButton()
             || focusedView == m_vScrollBar.getScrollButton()) {
                    m_vScrollBar.setAddSpeed(0);
                    return;
                }
            }
            if (m_allowDragScroll) {
                if (m_hScrollBar != null && m_hScrollBar.isVisible()) {
                    m_startMovePosX = m_hScrollBar.getPos();
                    m_hScrollBar.setAddSpeed(0);
                    m_readyToDragScroll = true;
                }
                if (m_vScrollBar != null && m_vScrollBar.isVisible()) {
                    m_startMovePosY = m_vScrollBar.getPos();
                    m_vScrollBar.setAddSpeed(0);
                    m_readyToDragScroll = true;
                }
                if (m_readyToDragScroll) {
                    m_startMovePoint = getNative().getTouchPoint();
                    m_startMoveTime = DateTime.Now;
                }
            }
        }

        /// <summary>
        /// 键盘按下方法
        /// </summary>
        /// <param name="key">按键</param>
        public override void onKeyDown(char key) {
            base.onKeyDown(key);
            FCHost host = getNative().getHost();
            if (!host.isKeyPress(0x10) && !host.isKeyPress(0x11) && !host.isKeyPress(0x12)) {
                //向上
                if (key == 38) {
                    lineUp();
                }
                //向下
                else if (key == 40) {
                    lineDown();
                }
                invalidate();
            }
        }

        /// <summary>
        /// 触摸按下方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchDown(FCTouchInfo touchInfo) {
            base.onTouchDown(touchInfo);
            if (!allowPreviewsEvent()) {
                onDragScrollStart();
            }
        }

        /// <summary>
        /// 触摸移动方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchMove(FCTouchInfo touchInfo) {
            base.onTouchMove(touchInfo);
            if (!allowPreviewsEvent()) {
                onDragScrolling();
            }
        }

        /// <summary>
        /// 触摸抬起方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchUp(FCTouchInfo touchInfo) {
            base.onTouchUp(touchInfo);
            if (!allowPreviewsEvent())
            {
                onDragScrollEnd();
            }
        }

        /// <summary>
        /// 触摸滚动方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchWheel(FCTouchInfo touchInfo) {
            base.onTouchWheel(touchInfo);
            if (m_vScrollBar != null && m_vScrollBar.isVisible())
            {
                if (touchInfo.m_delta > 0)
                {
                    lineUp();
                }
                else if (touchInfo.m_delta < 0)
                {
                    lineDown();
                }
            }
            else if (m_hScrollBar != null && m_hScrollBar.isVisible())
            {
                if (touchInfo.m_delta > 0)
                {
                    lineLeft();
                }
                else if (touchInfo.m_delta < 0)
                {
                    lineRight();
                }
            }
        }

        /// <summary>
        /// 预处理触摸事件
        /// </summary>
        /// <param name="eventName">事件ID</param>
        /// <param name="touchInfo">触摸信息</param>
        /// <returns>状态</returns>
        public override bool onPreviewsTouchEvent(String eventName, FCTouchInfo touchInfo) {
            if (callPreviewsTouchEvents("onpreviewstouchevent", eventName, touchInfo)) {
                return true;
            }
            if (allowPreviewsEvent())
            {
                if (eventName == "ontouchdown") {
                    onDragScrollStart();
                }
                else if (eventName == "ontouchmove") {
                    onDragScrolling();
                }
                else if (eventName == "ontouchup") {
                    bool state = m_isDragScrolling;
                    onDragScrollEnd();
                    if (state && !m_isDragScrolling2) {
                        return false;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 向下翻一页
        /// </summary>
        public virtual void pageDown() {
            if (m_vScrollBar != null && m_vScrollBar.isVisible()) {
                m_vScrollBar.pageAdd();
            }
        }

        /// <summary>
        /// 向左翻一页
        /// </summary>
        public virtual void pageLeft() {
            if (m_hScrollBar != null && m_hScrollBar.isVisible()) {
                m_hScrollBar.pageReduce();
            }
        }

        /// <summary>
        /// 向右翻一页
        /// </summary>
        public virtual void pageRight() {
            if (m_hScrollBar != null && m_hScrollBar.isVisible()) {
                m_hScrollBar.pageAdd();
            }
        }

        /// <summary>
        /// 向上翻一页
        /// </summary>
        public virtual void pageUp() {
            if (m_vScrollBar != null && m_vScrollBar.isVisible()) {
                m_vScrollBar.pageReduce();
            }
        }

        /// <summary>
        /// 设置属性值
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">属性值</param>
        public override void setAttribute(String name, String value) {
            switch (name)
            {
                case "allowdragscroll":
                    setAllowDragScroll(FCTran.strToBool(value));
                    break;
                case "showhscrollbar":
                    setShowHScrollBar(FCTran.strToBool(value));
                    break;
                case "showvscrollbar":
                    setShowVScrollBar(FCTran.strToBool(value));
                    break;
                default:
                    base.setAttribute(name, value);
                    break;
            }
        }

        /// <summary>
        /// 更新布局方法
        /// </summary>
        public override void update() {
            if (m_native != null && !m_native.m_lockUpdate)
            {
                base.update();
                updateScrollBar();
            }
        }

        /// <summary>
        /// 更新滚动条的布局
        /// </summary>
        public virtual void updateScrollBar() {
            if (getNative() != null) {
                FCHScrollBar hScrollBar = getHScrollBar();
                FCVScrollBar vScrollBar = getVScrollBar();
                if (isVisible()) {
                    int width = getWidth(), height = getHeight();
                    //滚动条尺寸         
                    int hBarHeight = (hScrollBar != null) ? hScrollBar.getHeight() : 0;
                    int vBarWidth = (vScrollBar != null) ? vScrollBar.getWidth() : 0;
                    int wmax = getContentWidth(), hmax = getContentHeight();
                    if (hScrollBar != null) {
                        hScrollBar.setContentSize(wmax);
                        hScrollBar.m_size = new FCSize(width - vBarWidth, hBarHeight);
                        hScrollBar.setPageSize(width - vBarWidth);
                        hScrollBar.m_location = new FCPoint(0, height - hBarHeight);
                        if (wmax <= width) {
                            hScrollBar.setVisible(false);
                        }
                        else {
                            hScrollBar.setVisible(true);
                        }
                    }
                    if (vScrollBar != null) {
                        vScrollBar.setContentSize(hmax);
                        vScrollBar.m_size = new FCSize(vBarWidth, height - hBarHeight);
                        vScrollBar.setPageSize(height - hBarHeight);
                        vScrollBar.m_location = new FCPoint(width - vBarWidth, 0);
                        int vh = (hScrollBar != null && hScrollBar.isVisible()) ? height - hBarHeight : height;
                        if (hmax <= vh) {
                            vScrollBar.setVisible(false);
                        }
                        else {
                            vScrollBar.setVisible(true);
                        }
                    }
                    //修改尺寸
                    if (hScrollBar != null && vScrollBar != null) {
                        if (hScrollBar.isVisible() && !vScrollBar.isVisible()) {
                            hScrollBar.m_size.cx = width;
                            hScrollBar.setPageSize(width);
                        }
                        else if (!hScrollBar.isVisible() && vScrollBar.isVisible()) {
                            vScrollBar.m_size.cy = height;
                            vScrollBar.setPageSize(height);
                        }
                    }
                    if (hScrollBar != null && hScrollBar.isVisible()) {
                        hScrollBar.update();
                    }
                    if (vScrollBar != null && vScrollBar.isVisible()) {
                        vScrollBar.update();
                    }
                }
            }
        }
    }
}
